Completed
Push — master ( 25e94b...33b2ef )
by Sander
01:31
created

$j.ready   C

Complexity

Conditions 8
Paths 7

Size

Total Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 0
Metric Value
cc 8
c 5
b 1
f 0
nc 7
nop 1
dl 0
loc 43
rs 5.3846
1
/* global API */
2
var $j = jQuery.noConflict();
3
4
$j(document).ready(function () {
5
6
    $j(document).click(function(event) {
7
        var passwordPickerRef = '.passwordPickerIframe';
8
        if(!$j(event.target).closest(passwordPickerRef).length) {
9
            if($j(passwordPickerRef).is(":visible")) {
10
                removePasswordPicker();
11
            }
12
        }
13
    });
14
15
    var _this = this;
16
    Array.prototype.findUrl = function (match) {
0 ignored issues
show
Compatibility Best Practice introduced by
You are extending the built-in type Array. This may have unintended consequences on other objects using this built-in type. Consider subclassing instead.
Loading history...
17
        return this.filter(function (item) {
18
            return typeof item === 'string' && item.indexOf(match) > -1;
19
        });
20
    };
21
22
    function removePasswordPicker() {
23
        $j('.passwordPickerIframe').remove();
24
    }
25
26
    _this.removePasswordPicker = removePasswordPicker;
27
28
    function enterLoginDetails(login) {
29
        var username;
30
31
        if (login.hasOwnProperty('username')) {
32
            username = (login.username !== '' ) ? login.username : login.email;
33
        }
34
        if(!username){
35
            username = null;
36
        }
37
38
        fillPassword(username, login.password);
39
        if ($j('.passwordPickerIframe').is(':visible')) {
40
            removePasswordPicker();
41
        }
42
    }
43
44
    _this.enterLoginDetails = enterLoginDetails;
45
46
    function getMaxZ() {
47
        return Math.max.apply(null,
48
            $j.map($j('body *'), function (e) {
49
                if ($j(e).css('position') !== 'static')
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if $j(e).css("position") !== "static" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
50
                    return parseInt($j(e).css('z-index')) || 1;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
51
            }));
52
    }
53
54
    function showPasswordPicker(form) {
55
        var jPasswordPicker = $j('.passwordPickerIframe');
56
        if (jPasswordPicker.length > 1) {
57
            return;
58
        }
59
        var loginField = $j(form[0]);
60
        var loginFieldPos = loginField.offset();
61
        var loginFieldVisible = loginField.is(':visible');
62
63
        var position = $j(form[1]).position();
0 ignored issues
show
Unused Code introduced by
The assignment to variable position seems to be never used. Consider removing it.
Loading history...
64
        var passwordField = $j(form[1]);
65
        var passwordFieldPos = passwordField.offset();
66
        var passwordFieldVisible = loginField.is(':visible');
0 ignored issues
show
Unused Code introduced by
The variable passwordFieldVisible seems to be never used. Consider removing it.
Loading history...
67
        var left = (loginFieldPos) ? loginFieldPos.left : passwordFieldPos.left;
68
        var top = (loginFieldPos) ? loginFieldPos.top : passwordFieldPos.top;
69
        var maxZ = getMaxZ();
70
71
        if (loginFieldPos && passwordFieldPos.top > loginFieldPos.top) {
72
            //console.log('login fields below each other')
73
            top = passwordFieldPos.top + passwordField.height() + 10;
74
        } else {
75
            // console.log('login fields next to each other')
76
            if(loginFieldPos){
77
                top =  top + loginField.height() + 10;
78
            } else {
79
                top =  top + passwordField.height() + 10;
80
            }
81
        }
82
        if(!loginFieldVisible){
83
            left = passwordFieldPos.left;
84
        }
85
86
        var pickerUrl = API.extension.getURL('/html/inject/password_picker.html');
87
88
        var picker = $j('<iframe class="passwordPickerIframe" scrolling="no" height="385" width="350" frameborder="0" src="' + pickerUrl + '"></iframe>');
89
        picker.css('position', 'absolute');
90
        picker.css('left', left);
91
        picker.css('z-index', maxZ + 10);
92
        picker.css('top', top);
93
        $j('body').prepend($j(picker));
94
        // picker.css('width', $j(form).width());
95
        $j('.passwordPickerIframe:not(:last)').remove();
96
    }
97
98
    function onFormIconClick(e) {
99
        e.preventDefault();
100
        e.stopPropagation();
101
        var offsetX = e.offsetX;
102
        var offsetRight = (e.data.width - offsetX);
103
        if (offsetRight < e.data.height) {
104
            showPasswordPicker(e.data.form);
105
        }
106
    }
107
108
    function createFormIcon(el, form) {
109
        var offset = el.offset();
0 ignored issues
show
Unused Code introduced by
The assignment to variable offset seems to be never used. Consider removing it.
Loading history...
110
        var width = el.width();
111
        var height = el.height() * 1;
112
        var margin = (el.css('margin')) ? parseInt(el.css('margin').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
113
        var padding = (el.css('padding')) ? parseInt(el.css('padding').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable padding seems to be never used. Consider removing it.
Loading history...
114
115
        var pickerIcon = API.extension.getURL('/icons/icon.svg');
116
        $j(el).css('background-image', 'url("' + pickerIcon + '")');
117
        $j(el).css('background-repeat', 'no-repeat');
118
        //$j(el).css('background-position', '');
119
        $j(el).css('cssText', el.attr('style')+' background-position: right 3px center !important;');
120
121
        $j(el).unbind('click', onFormIconClick);
122
        $j(el).click({width: width, height: height, form: form}, onFormIconClick);
123
    }
124
125
    function createPasswordPicker(form) {
126
        for (var i = 0; i < form.length; i++) {
127
            var el = $j(form[i]);
128
            createFormIcon(el, form);
129
130
        }
131
    }
132
133
    function formSubmitted(fields) {
134
        var user = fields[0].value;
135
        var pass = fields[1].value;
136
        var params = {
137
            username: user,
138
            password: pass
139
        };
140
        //Disable password mining
141
        //$j(fields[1]).attr('type', 'hidden');
142
        API.runtime.sendMessage(API.runtime.id, {method: "minedForm", args: params});
143
144
    }
145
146
    function inIframe() {
147
        try {
148
            return window.self !== window.top;
149
        } catch (e) {
150
            return true;
151
        }
152
    }
153
154
    function showDoorhanger(data) {
155
        if (inIframe()) {
156
            return;
157
        }
158
        data.data.currentLocation = window.location.href;
159
        API.runtime.sendMessage(API.runtime.id, {method: "setDoorhangerData", args: data});
160
        var pickerUrl = API.extension.getURL('/html/inject/doorhanger.html');
161
162
        var doorhanger = $j('<iframe id="password-toolbarIframe" style="display: none;" scrolling="no" height="60" width="100%" frameborder="0" src="' + pickerUrl + '"></iframe>');
163
        $j('#password-toolbarIframe').remove();
164
        doorhanger.css('z-index',  getMaxZ() + 1);
165
        $j('body').prepend(doorhanger);
166
        $j('#password-toolbarIframe').fadeIn();
167
    }
168
169
    _this.showDoorhanger = showDoorhanger;
170
171
    function showUrlUpdateDoorhanger(data) {
172
        var buttons = ['cancel', 'updateUrl'];
173
        showDoorhanger({
174
            data: data.data,
175
            buttons: buttons
176
        });
177
    }
178
179
    _this.showUrlUpdateDoorhanger = showUrlUpdateDoorhanger;
180
181
    function checkForMined() {
182
        if (inIframe()) {
183
            return;
184
        }
185
186
        API.runtime.sendMessage(API.runtime.id, {method: "getMinedData"}).then(function (data) {
187
            if (!data) {
188
                return;
189
            }
190
            if (data.hasOwnProperty('username') && data.hasOwnProperty('password') && data.hasOwnProperty('url')) {
191
                var buttons = [ 'cancel', 'ignore', 'save' ];
192
                showDoorhanger({data: data, buttons: buttons});
193
            }
194
        });
195
    }
196
197
198
    function closeDoorhanger() {
199
        $j('#password-toolbarIframe').hide(400);
200
        $j('#password-toolbarIframe').remove();
201
    }
202
203
    _this.closeDoorhanger = closeDoorhanger;
204
205
    function initForms() {
206
        API.runtime.sendMessage(API.runtime.id, {method: 'getRuntimeSettings'}).then(function (settings) {
207
            var disablePasswordPicker = settings.disablePasswordPicker;
208
            var url = window.location.href;
209
            var loginFields = getLoginFields();
210
            if (loginFields.length > 0) {
211
                for (var i = 0; i < loginFields.length; i++) {
212
                    var form = getFormFromElement(loginFields[i][0]);
213
                    if (!disablePasswordPicker) {
214
                        createPasswordPicker(loginFields[i], form);
0 ignored issues
show
Bug introduced by
The call to createPasswordPicker seems to have too many arguments starting with form.
Loading history...
215
                    }
216
                    //Password miner
217
                    /* jshint ignore:start */
218
                    if (!settings.hasOwnProperty('ignored_sites') || settings.ignored_sites.findUrl(url) !== -1) {
219
                        $j(form).submit((function (loginFields) {
220
                            return function () {
221
                                formSubmitted(loginFields);
222
                            };
223
                        })(loginFields[i]));
224
                    }
225
                    /* jshint ignore:end */
226
                }
227
228
                API.runtime.sendMessage(API.runtime.id, {
229
                    method: "getCredentialsByUrl",
230
                    args: url
231
                }).then(function (logins) {
232
                    console.log('Found ' + logins.length + ' logins for this site');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
233
                    if (logins.length === 1) {
234
                        API.runtime.sendMessage(API.runtime.id, {method: 'isAutoFillEnabled'}).then(function (isEnabled) {
235
                            if (isEnabled) {
236
                                enterLoginDetails(logins[0]);
237
                            }
238
                        });
239
                    }
240
241
                });
242
            }
243
244
        });
245
    }
246
247
    function minedLoginSaved(args) {
248
        // If the login added by the user then this is true
249
        if (args.selfAdded) {
250
            enterLoginDetails(args.credential);
251
        }
252
    }
253
254
    _this.minedLoginSaved = minedLoginSaved;
255
256
    function resizeIframe(height) {
257
        $j('#password-toolbarIframe').height(60 + height);
258
    }
259
260
    _this.resizeIframe = resizeIframe;
261
262
    function copyText(text) {
263
        var txtToCopy = document.createElement('input');
264
        txtToCopy.style.left = '-300px';
265
        txtToCopy.style.position = 'absolute';
266
        txtToCopy.value = text;
267
        document.body.appendChild(txtToCopy);
268
        txtToCopy.select();
269
        document.execCommand('copy');
270
        txtToCopy.parentNode.removeChild(txtToCopy);
271
    }
272
273
    _this.copyText = copyText;
274
275
    function init() {
276
        checkForMined();
277
        initForms();
278
    }
279
280
    var readyStateCheckInterval = setInterval(function () {
281
        if (document.readyState === "complete") {
282
            clearInterval(readyStateCheckInterval);
283
            API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'}).then(function (result) {
284
                if (result) {
285
                    init();
286
                    var body = document.getElementsByTagName('body')[0];
287
                    observeDOM(body, initForms);
288
                } else {
289
                    console.log('[Passman extension] Stopping, vault key not set');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
290
                }
291
            });
292
        }
293
    }, 10);
294
295
    API.runtime.onMessage.addListener(function (msg, sender) {
296
        //console.log('Method call', msg.method);
297
        if (_this[msg.method]) {
298
            _this[msg.method](msg.args, sender);
299
        }
300
    });
301
});
302